package com.infolab.aims.web;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;

import com.infolab.aims.GlobalConstant;
import com.infolab.aims.common.AbstractController;
import com.infolab.aims.common.ParameterDateQueryHelper;
import com.infolab.aims.common.SpecialToStringStyle;
import com.infolab.aims.common.bean.SearchCriteria;
import com.infolab.aims.common.bean.SearchResult;
import com.infolab.aims.domain.Audit;
import com.infolab.aims.service.intf.AuditService;

@Controller
@RequestMapping("/audit")
@SessionAttributes(value = AuditController.SESSION_SEARCH_CRITERIA)
public class AuditController extends AbstractController {

	public static final String SESSION_SEARCH_CRITERIA = "searchCriteria";
	public static final String CONTEXT_PATH = "/audit";
	public static final String JSP_MAIN_SEARCH = "auditSearch";
	public static final String JSP_MAIN_FORM = "auditForm";
	Log logger = LogFactory.getLog(getClass());
	public static final String UPDATE_OPERTAION = "update";

	@Autowired
	AuditService auditService;

	@RequestMapping(value = "search")
	public String searchAudit(@ModelAttribute(AuditController.SESSION_SEARCH_CRITERIA) SearchCriteria searchCriteria,
			@ModelAttribute("currentSearchCriteria") SearchCriteria currentSearchCriteria, Model model) {

		if (currentSearchCriteria.getCurPage() != null)
			searchCriteria.setCurPage(currentSearchCriteria.getCurPage());

		Date dateFrom = null;
		Date dateTo = null;

		try {
			if (!checkNullEmpty(searchCriteria.getSearchCriteria("dateFrom"))) {
				dateFrom = new SimpleDateFormat(GlobalConstant.DATE_FORMAT_JAVA).parse(searchCriteria.getSearchCriteria("dateFrom")
						.toString());
			}
		} catch (ParseException e) {
			searchCriteria.addSearchCriteria("dateFrom", "");
		}

		try {

			if (!checkNullEmpty(searchCriteria.getSearchCriteria("dateTo"))) {
				dateTo = new SimpleDateFormat(GlobalConstant.DATE_FORMAT_JAVA).parse(searchCriteria.getSearchCriteria("dateTo").toString());
			}
		} catch (ParseException e) {
			searchCriteria.addSearchCriteria("dateTo", "");
		}

		if (currentSearchCriteria.getCurPage() != null)
			searchCriteria.setCurPage(currentSearchCriteria.getCurPage());

		if (!checkNullEmpty(dateFrom) && !checkNullEmpty(dateTo)) {

			searchCriteria.addSearchCriteria("dateModified", new ParameterDateQueryHelper("dateModified", dateFrom, dateTo));
		}

		else if (!checkNullEmpty(dateFrom) && checkNullEmpty(dateTo)) {
			searchCriteria.addSearchCriteria("dateModified", new ParameterDateQueryHelper("dateModified", dateFrom, null));
		}

		else if (checkNullEmpty(dateFrom) && !checkNullEmpty(dateTo)) {
			searchCriteria.addSearchCriteria("dateModified", new ParameterDateQueryHelper("dateModified", null, dateTo));
		}

		else {
			searchCriteria.addSearchCriteria("dateModified", new ParameterDateQueryHelper("dateModified", null, null));
		}

		SearchResult searchResult = auditService.searchAduit(searchCriteria);
		model.addAttribute(searchResult);

		return JSP_MAIN_SEARCH;
	}

	@RequestMapping(value = {"detail/{id}"}, method = RequestMethod.GET)
	public String detailAudit(@PathVariable String id, Model model) {
		Audit audit = auditService.getAudit(NumberUtils.toLong(id));
		if(audit != null){
			List<Audit> list = new ArrayList<Audit>();
			String operation = audit.getOperation()!=null? audit.getOperation():"";
			if(StringUtils.equals(operation, UPDATE_OPERTAION)){	
				SearchCriteria searchCriteria = new SearchCriteria();				
				searchCriteria.addSearchCriteria("auditId", audit.getAuditId());
				Audit pre = auditService.findAudit(searchCriteria);			// Find if the audit is having any history information
				if(pre != null){
					list.add(pre);
				} 
			}
			list.add(audit);
			model.addAttribute("records", parseRecords(list));
		}
		return JSP_MAIN_FORM;
	}

	@ModelAttribute(AuditController.SESSION_SEARCH_CRITERIA)
	public SearchCriteria getAuditSearchCriteria() {
		return new SearchCriteria(); 
	}

	public static List<Map<String, String>> parseRecords(List<Audit> list) {
		List<Map<String, String>> records = new ArrayList<Map<String, String>>();
		if (CollectionUtils.isNotEmpty(list)) {
			for (Audit audit : list) {
				if(audit == null){
					continue;
				}
				Map<String, String> record = new LinkedHashMap<String, String>();
				String str1 = audit.getContentHead();
				Pattern p = Pattern.compile("\\[(.+)]");
				Matcher m = p.matcher(str1);
				boolean result = m.find();
				if (result) {
					record.put("Modified By", audit.getModifiedBy());
					record.put("Modified Date", audit.getLastModifiedDate());
					String total = m.group(1);
					String[] arr = StringUtils.split(total, SpecialToStringStyle.SPECIAL_SEPARATE);
					for (String str : arr) {
						String[] inner = StringUtils.split(str, "=");
						if (inner != null && inner.length > 1) {
							record.put(inner[0], inner[1]);
						}
					}
					String str2 = audit.getContentDetail();
					if (StringUtils.isNotEmpty(str2)) {
						record.put("Detail", str2);
					}
					records.add(record);
				}
			}
		}
		return records;

	}

	public boolean checkNullEmpty(Object obj) {

		boolean flag = true;
		if (obj != null && !obj.equals("")) {
			flag = false;
		}
		return flag;

	}
}
